#pragma once
#include <iostream>
#include <memory>
#include <unordered_map>

#include "Epoller.hpp"
#include "Connetion.hpp"

using namespace EpollModule;

using connection_t = std::shared_ptr<Connection>;

class EpollServer
{
    static const int event_num = 64;
public:
    EpollServer()
        :_epoller(std::make_unique<Epoller>())
        ,_isrunning(false)
        {
            _epoller->Init();
        }


    void InsertConnection(connection_t &conn)
    {
        auto iter = _connections.find(conn->Sockfd());
        if(iter == _connections.end())
        {
            //1,把连接，放到unordered_map中进行管理
            _connections.insert(std::make_pair(conn->Sockfd(), conn));
            //2,把新插入进来的连接，写透到内核的epoll中
            LOG(LogLevel::WARNING) << "conn->Sockfd() : "<< conn->Sockfd();
            
            _epoller->Ctrl(conn->Sockfd(), conn->GetEvents());
        }
    }

    bool IsConnectionExists(int sockfd)
    {
        return _connections.find(sockfd) != _connections.end();
    }

    void Loop()
    {
        _isrunning = true;
        while(_isrunning)
        {
            int n = _epoller->Wait(_revs, event_num);
            LOG(LogLevel::ERROR) << "n: " << n;
            // sleep(10000);
            for(int i = 0; i< n; i++)
            {
                //开始进行派发， 派发到指定的模块
                int sockfd = _revs[i].data.fd;
                uint16_t revents = _revs[i].events;
                if((revents & EPOLLERR) || (revents & EPOLLHUP))
                    revents = (EPOLLIN | EPOLLOUT); //异常事件，转换为读写事件
                
                if((revents&EPOLLIN) && IsConnectionExists(sockfd))
                {
                    _connections[sockfd]->CallRecv();
                }
                if((revents&EPOLLOUT) && IsConnectionExists(sockfd))
                {
                    _connections[sockfd]->CallSend();
                }
            }
        }
        _isrunning = false;
    }

    void Stop()
    {
        _isrunning = true;
    }

    ~EpollServer()
    {}

private:
    std::unique_ptr<Epoller> _epoller; //不要忘记初始化
    std::unordered_map<int, connection_t> _connections; //fd :Connections
    bool _isrunning;
    struct epoll_event _revs[event_num];
};